package com.lanhao.aot.anthouse;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;

public class AntHouseIntegration {
	private static final Logger LOG = LoggerFactory.getLogger(AntHouseIntegration.class);
	public static final String ROLE = "xunfei";  // 固定值
	public static final String APPID = "Pbff9oQ4CbTAED71"; // 固定值
	public static final String APPKEY = "aF1PzRqF77DaPn2n"; // 固定值
	public static final String DEVICE_MAC = "2cd26b6875e0"; // 不固定，是带屏网关的mac地址，绑定时需要在IOT平台存储
	public static final String FromUserName = "18056869725"; // 固定值，公共账号信息
	public static final String MESSAGE_DEV_SEARCH = "dev_search_by_class";
	public static final String MESSAGE_ROOM_MANAGE = "room_manager";
	public static final String SUCCESS = "success";
	public static final Boolean cmdSwitch = true;
	public static final String GET_DYNAMIC_KEY_URL = "http://server.atsmartlife.com/get_dynamic_passwd_thirdly";
	public static final String POS_DATA_URL = "http://server.atsmartlife.com/postmsg";
	public static final String GET_DATA_URL = "http://server.atsmartlife.com/getmsg?token={}&role={}&from_username={}";
	public static final ScheduledExecutorService newSchThreadPool = Executors.newSingleThreadScheduledExecutor();

	public static void main(String[] args) {
		// 1、获取动态密钥信息
		String dynamicKeyResp = getDynamicKey();
		JSONObject respObject = JSON.parseObject(dynamicKeyResp);
		String dynamicPasswd = respObject.getString("dynamic_passwd");
		// 2、账户登录信息
		String loginResult = login(FromUserName, dynamicPasswd);
		JSONObject tokenResultObject = JSON.parseObject(loginResult);
		String token = tokenResultObject.getString("token");
		// 3、 发送小网关指令搜索指令
		String decoceCmdResult = sendDevSearchCmd(FromUserName, token, dynamicPasswd);
		JSONObject cmdObject = JSON.parseObject(decoceCmdResult);
		String devSearchCmdResult = cmdObject.getString("result");
		if (!SUCCESS.equals(devSearchCmdResult)) {
			LOG.error("小网关搜索发送命令失败");
		}
		String msgQryUrl = StrUtil.format(GET_DATA_URL, token, ROLE, FromUserName);
		// 4、轮询小网关搜索结果
		JSONObject devSearchQry = devSearchQry(msgQryUrl, dynamicPasswd);
		
		// 5、通过查询到小网关mac信息，查询该网关下绑定的子设备清单，并将设备信息和房间信息同步到小网关
		// TODO 待实现
		
		// 如果服务端能够得到小网关所在room_id，那么6、7步可忽略。
		
		// 6、发送房间查询命令
		String roomManageResult = sendRoomManageCmd(FromUserName, token, dynamicPasswd);
		JSONObject roomManageObject = JSON.parseObject(roomManageResult);
		String roomManageCmdResult = roomManageObject.getString("result");
		if (!SUCCESS.equals(roomManageCmdResult)) {
			LOG.error("房间信息查询发送命令失败");
		}
		// 7、轮询房间信息，得到小网关所在房间
		JSONArray roomQry = roomQry(msgQryUrl, dynamicPasswd);
		// 8、发送设备管理命令 -  需要以小网关信息和所在房间信息作为入参
		String devManageResult = sendDevManageCmd(FromUserName, token, dynamicPasswd, devSearchQry, roomQry);
		LOG.info("设备管理命令发送结果result={}", devManageResult);
	}

	public static String getDynamicKey() {
		try {
			JSONObject request = new JSONObject();
			request.put("cmd", "get_dynamic_passwd_thirdly");
			request.put("app_id", APPID);
			request.put("role", ROLE);
			JSONObject data = new JSONObject();
			data.put("time", System.currentTimeMillis() / 1000);
			data.put("from_username", FromUserName);
			String encryptData = AESUtil.encodeByKey(data.toJSONString(), APPKEY);
			request.put("data", encryptData);
			String resultString = HttpRequest.post(GET_DYNAMIC_KEY_URL).body(request.toJSONString()).execute().body();
			JSONObject resultObject = JSON.parseObject(resultString);
			String result = resultObject.getString("result");
			if (!SUCCESS.equals(result)) {
				LOG.error("获取动态密钥信息失败");
				return "";
			}
			String respData = resultObject.getString("data");
			String dynamicKeyResp = AESUtil.getDecodeByKey(respData, APPKEY);
			LOG.info("1、获取动态密钥url={}, data={}, request={}, 结果result={},解密后结果={}", GET_DYNAMIC_KEY_URL,
					data.toJSONString(), request.toJSONString(), resultString, dynamicKeyResp);
			return dynamicKeyResp;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	public static String login(String fromUserName, String dynamicPasswd) {
		JSONObject request = new JSONObject();
		request.put("from_username", fromUserName);
		request.put("role", ROLE);
		JSONObject data = new JSONObject();
		data.put("cmd", "login_thirdly");
		data.put("password", "alsoapig");
		data.put("from_username", fromUserName);
		data.put("role", ROLE);
		data.put("appid", APPID);
		String encryptData = AESUtil.encodeByKey(data.toJSONString(), dynamicPasswd);
		request.put("data", encryptData);
		String loginResult = HttpRequest.post(POS_DATA_URL).body(request.toJSONString()).execute().body();
		String decodeLoginResult = AESUtil.getDecodeByKey(loginResult, dynamicPasswd);
		LOG.info("2、登录流程：url={}. data={}, request={}, 结果loginResult={}，解密后结果decodeLoginResult={}", POS_DATA_URL,
				data.toJSONString(), request.toJSONString(), loginResult, decodeLoginResult);
		return decodeLoginResult;
	}

	public static JSONObject devSearchQry(String msgQryUrl, String dynamicPasswd) {
		AtomicBoolean cmdSuccess = new AtomicBoolean(false);
		JSONObject devSearchResult = null;
		do {
			String getMsgResult = getRemoteMessage.apply(msgQryUrl);
			String decodeMsgResult = AESUtil.getDecodeByKey(getMsgResult, dynamicPasswd);
			LOG.info("4、获取小网关搜索云端指令下发结果url={}, 结果={}，解密后结果decodeMsgResult={}", msgQryUrl, getMsgResult, decodeMsgResult);
			JSONObject msgResultObject = JSON.parseObject(decodeMsgResult);
			String devSearchmsg = msgResultObject.getString("msg");
			JSONObject devSearchMsgObject = JSON.parseObject(devSearchmsg);
			if (devSearchMsgObject != null) {
				String msgType = devSearchMsgObject.getString("msg_type");
				JSONArray devices = devSearchMsgObject.getJSONArray("devices");
				boolean success = MESSAGE_DEV_SEARCH.equals(msgType) && (devices != null && devices.size() > 0);
				if (success) {
					LOG.info("小网关信息搜索成功，devSearchmsg={}", devSearchmsg);
					devSearchResult = devices.getJSONObject(0);
				}
				cmdSuccess.set(success);
			}
		} while (!cmdSuccess.get());

		return devSearchResult;
	}

	public static JSONArray roomQry(String msgQryUrl, String dynamicPasswd) {
		AtomicBoolean roomQuerysuccess = new AtomicBoolean(false);
		JSONArray roomQryResult = null;
		do {
			String getMsgResult = getRemoteMessage.apply(msgQryUrl);
			String decodeMsgResult = AESUtil.getDecodeByKey(getMsgResult, dynamicPasswd);
			LOG.info("6、获取云端房间查询结果msg:url={}, 结果={}，解密后结果decodeMsgResult={}", msgQryUrl, getMsgResult, decodeMsgResult);
			JSONObject msgResultObject = JSON.parseObject(decodeMsgResult);
			String roomQryMsg = msgResultObject.getString("msg");
			JSONObject roomQryMsgObject = JSON.parseObject(roomQryMsg);
			if (roomQryMsgObject != null) {
				String msgType = roomQryMsgObject.getString("msg_type");
				JSONArray rooms = roomQryMsgObject.getJSONArray("rooms");
				boolean success = MESSAGE_ROOM_MANAGE.equals(msgType) && (rooms != null && rooms.size() > 0);
				if (success) {
					LOG.info("云端房间查询成功，roomQrymsg={}", roomQryMsg);
					roomQryResult = rooms;
				}
				roomQuerysuccess.set(success);
			}
		} while (!roomQuerysuccess.get());

		return roomQryResult;
	}

	public static String sendDevSearchCmd(String fromUserName, String token, String dynamicPasswd) {
		JSONObject request = new JSONObject();

		request.put("from_username", fromUserName);
		request.put("role", ROLE);

		JSONObject data = new JSONObject();
		data.put("cmd", "send_msg");
		data.put("to_username", DEVICE_MAC); // 带屏网关的mac地址
		data.put("token", token);

		JSONObject msgObject = new JSONObject();
		msgObject.put("msg_type", "dev_search_by_class");
		msgObject.put("command", "query");
		msgObject.put("from_role", ROLE);
		msgObject.put("from_account", fromUserName);
		msgObject.put("dev_class_b_type", "coordin_zigbee");
		msgObject.put("dev_base_ids", new JSONArray());
		data.put("msg", msgObject.toJSONString());
		data.put("subject", "control");

		String encryptData = AESUtil.encodeByKey(data.toJSONString(), dynamicPasswd);
		request.put("data", encryptData);

		String sendCmdResult = HttpRequest.post(POS_DATA_URL).body(request.toJSONString()).execute().body();
		String decodeCmdSendResult = AESUtil.getDecodeByKey(sendCmdResult, dynamicPasswd);
		LOG.info("3、向带屏网关发送扫描指令：Post数据url={}. data={}, request={}, 结果result={}，解密后结果decodeCmdSendResult={}",
				POS_DATA_URL, data.toJSONString(), request.toJSONString(), sendCmdResult, decodeCmdSendResult);
		return decodeCmdSendResult;
	}

	// 发送房间查询
	public static String sendRoomManageCmd(String fromUserName, String token, String dynamicPasswd) {

		JSONObject request = new JSONObject();

		request.put("from_username", fromUserName);
		request.put("role", ROLE);

		JSONObject data = new JSONObject();
		data.put("cmd", "send_msg");
		data.put("to_username", DEVICE_MAC); // 带屏网关的mac地址
		data.put("token", token);

		JSONObject msgObject = new JSONObject();
		msgObject.put("msg_type", "room_manager");
		msgObject.put("command", "query");
		msgObject.put("from_role", ROLE);
		msgObject.put("from_account", fromUserName);
		msgObject.put("room_id", -1);

		data.put("msg", msgObject.toJSONString());
		data.put("subject", "control");

		String encryptData = AESUtil.encodeByKey(data.toJSONString(), dynamicPasswd);
		request.put("data", encryptData);

		String sendRoomManageResult = HttpRequest.post(POS_DATA_URL).body(request.toJSONString()).execute().body();
		String decodeRoomManageResult = AESUtil.getDecodeByKey(sendRoomManageResult, dynamicPasswd);
		LOG.info("5、发送房间查询指令：Post数据url={}. data={}, request={}, 结果result={}，解密后结果decodeRoomManageResult={}",
				POS_DATA_URL, data.toJSONString(), request.toJSONString(), sendRoomManageResult,
				decodeRoomManageResult);
		return decodeRoomManageResult;
	}

	// 发送房间查询
	public static String sendDevManageCmd(String fromUserName, String token, String dynamicPasswd, JSONObject devSearchQry, JSONArray roomQry) {

		JSONObject request = new JSONObject();

		request.put("from_username", fromUserName);
		request.put("role", ROLE);

		JSONObject data = new JSONObject();
		data.put("cmd", "send_msg");
		data.put("to_username", DEVICE_MAC); // 带屏网关的mac地址
		data.put("token", token);
		
		String hostMac = devSearchQry.getString("host_mac");
		String devNetAddr = devSearchQry.getString("dev_net_addr");
		String devMacAddr = devSearchQry.getString("dev_mac_addr");
		// 这里需要取小网关对应的房间ID信息
		int roomId = roomQry.getJSONObject(0).getIntValue("room_id");
		JSONObject msgObject = new JSONObject();
		msgObject.put("msg_type", "device_manager");
		msgObject.put("command", "add");
		msgObject.put("from_role", ROLE);
		msgObject.put("from_account", fromUserName);
		msgObject.put("room_id", roomId); //必值  整型 需要发查询房间的命令
		msgObject.put("dev_class_b_type", "coordin_zigbee");
		msgObject.put("host_mac", hostMac); //必值  字符型 来自搜索
		msgObject.put("dev_class_type", "coordin_zigbee"); //必值  字符型  coordin_zigbee
		msgObject.put("dev_base_id", 0); //必值  整型 默认0
		msgObject.put("dev_uptype", 0); //必值  整型 默认0
		msgObject.put("dev_name", "小网关设备"); //必值  字符型 自定义
		msgObject.put("dev_key", 0); //必值  整型 默认0
		msgObject.put("dev_mac_addr", devMacAddr); //必值  字符型   来自搜索
		msgObject.put("dev_net_addr", devNetAddr); //必值  字符型 来自搜索
		msgObject.put("dev_state", new JSONObject());
		msgObject.put("dev_lock", 0);
		msgObject.put("sensor", new JSONObject());

		data.put("msg", msgObject.toJSONString());
		data.put("subject", "control");

		String encryptData = AESUtil.encodeByKey(data.toJSONString(), dynamicPasswd);
		request.put("data", encryptData);

		String sendRoomManageResult = HttpRequest.post(POS_DATA_URL).body(request.toJSONString()).execute().body();
		String decodeRoomManageResult = AESUtil.getDecodeByKey(sendRoomManageResult, dynamicPasswd);
		LOG.info("7、发送设备管理指令：Post数据url={}. data={}, request={}, 结果result={}，解密后结果decodeDevManageResult={}",
				POS_DATA_URL, data.toJSONString(), request.toJSONString(), sendRoomManageResult,
				decodeRoomManageResult);
		return decodeRoomManageResult;
	}

	static Function<String, String> getRemoteMessage = (messageQryUrl) -> {
		String msgQryResult = HttpRequest.get(messageQryUrl).setConnectionTimeout(1000).setReadTimeout(90000).execute()
				.body();
		return msgQryResult;
	};
}
